﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace cstdx.Exchange;

/// <summary>
/// 证券市场相关工具类
/// </summary>
public static class ExchangeTool
{
	// 常量定义
	public const string StockDelisting = "DELISTING"; // 退市

	public const string MarketShangHai = "sh"; // 上海
	public const string MarketShenZhen = "sz"; // 深圳
	public const string MarketBeiJing = "bj";  // 北京
	public const string MarketHongKong = "hk"; // 香港
	public const string MarketUSA = "us";      // 美国

	public const string MARKET_CN_FIRST_DATE = "19901219";     // 上证指数的第一个交易日
	public const string MARKET_CH_FIRST_LISTTIME = "1990-12-19"; // 个股上市日期

	// 全部市场简写
	private static readonly string[] marketFlags = { "sh", "sz", "SH", "SZ", "bj", "BJ", "hk", "HK", "us", "US" };
	// A股市场代码
	private static readonly string[] marketAShareFlags = { "sh", "sz", "SH", "SZ", "bj", "BJ" };

	/// <summary>
	/// 获取证券代码（带市场前缀）
	/// </summary>
	public static string GetSecurityCode(MarketType market, string symbol)
	{
		switch (market)
		{
			case MarketType.MarketIdUSA:
				return MarketUSA + symbol;
			case MarketType.MarketIdHongKong:
				return symbol.Length >= 5 ? MarketHongKong + symbol.Substring(0, 5) : MarketHongKong + symbol;
			case MarketType.MarketIdBeiJing:
				return symbol.Length >= 6 ? MarketBeiJing + symbol.Substring(0, 6) : MarketBeiJing + symbol;
			case MarketType.MarketIdShenZhen:
				return symbol.Length >= 6 ? MarketShenZhen + symbol.Substring(0, 6) : MarketShenZhen + symbol;
			default:
				return symbol.Length >= 6 ? MarketShangHai + symbol.Substring(0, 6) : MarketShangHai + symbol;
		}
	}

	/// <summary>
	/// 判断股票ID对应的证券市场
	/// </summary>
	/// <remarks>
	/// ['50', '51', '60', '90', '110'] 为 sh
	/// ['00', '12'，'13', '18', '15', '16', '18', '20', '30', '39', '115'] 为 sz
	/// ['5', '6', '9'] 开头的为 sh， 其余为 sz
	/// </remarks>
	public static string GetMarket(string symbol)
	{
		symbol = symbol.Trim();
		string market = "sh";

		if (StartsWithAny(symbol, marketFlags))
		{
			market = symbol.Substring(0, 2).ToLower();
		}
		else if (EndsWithAny(symbol, marketFlags))
		{
			int length = symbol.Length;
			market = symbol.Substring(length - 2, 2).ToLower();
		}
		else if (StartsWithAny(symbol, new[] { "50", "51", "60", "68", "90", "110", "113", "132", "204" }))
		{
			market = "sh";
		}
		else if (StartsWithAny(symbol, new[] { "00", "12", "13", "18", "15", "16", "18", "20", "30", "39", "115", "1318" }))
		{
			market = "sz";
		}
		else if (StartsWithAny(symbol, new[] { "5", "6", "9", "7" }))
		{
			market = "sh";
		}
		else if (StartsWithAny(symbol, new[] { "88" }))
		{
			market = "sh";
		}
		else if (StartsWithAny(symbol, new[] { "4", "8" }))
		{
			market = "bj";
		}

		return market;
	}

	/// <summary>
	/// 获得市场ID
	/// </summary>
	public static MarketType GetMarketId(string symbol)
	{
		string market = GetMarket(symbol);
		return market switch
		{
			"sh" => MarketType.MarketIdShangHai,
			"sz" => MarketType.MarketIdShenZhen,
			"bj" => MarketType.MarketIdBeiJing,
			_ => MarketType.MarketIdShangHai
		};
	}

	/// <summary>
	/// 获取市场标识（简写）
	/// </summary>
	public static string GetMarketFlag(MarketType marketId)
	{
		return marketId switch
		{
			MarketType.MarketIdShenZhen => MarketShenZhen,
			MarketType.MarketIdBeiJing => MarketBeiJing,
			MarketType.MarketIdHongKong => MarketHongKong,
			MarketType.MarketIdUSA => MarketUSA,
			_ => MarketShangHai
		};
	}

	/// <summary>
	/// 检测市场代码
	/// </summary>
	/// <param name="symbol">证券代码</param>
	/// <param name="marketId">输出：市场ID</param>
	/// <param name="market">输出：市场标识</param>
	/// <param name="code">输出：纯代码（不含市场标识）</param>
	public static void DetectMarket(string symbol, out MarketType marketId, out string market, out string code)
	{
		code = symbol.Trim();
		market = MarketShangHai;

		if (StartsWithAny(code, marketFlags))
		{
			// 处理前缀格式（如SZ000002或SZ.000002）
			market = code.Substring(0, 2).ToLower();
			if (code.Length >= 3 && code[2] == '.')
			{
				code = code.Substring(3);
			}
			else
			{
				code = code.Substring(2);
			}
		}
		else if (EndsWithAny(code, marketFlags))
		{
			// 处理后缀格式（如600000.SH）
			int length = code.Length;
			market = code.Substring(length - 2, 2).ToLower();
			code = code.Substring(0, length - 3);
		}
		else if (StartsWithAny(code, new[] { "50", "51", "60", "68", "90", "110", "113", "132", "204" }))
		{
			market = MarketShangHai;
		}
		else if (StartsWithAny(code, new[] { "00", "12", "13", "18", "15", "16", "18", "20", "30", "39", "115", "1318" }))
		{
			market = MarketShenZhen;
		}
		else if (StartsWithAny(code, new[] { "5", "6", "9", "7" }))
		{
			market = MarketShangHai;
		}
		else if (StartsWithAny(code, new[] { "88" }))
		{
			market = MarketShangHai;
		}
		else if (StartsWithAny(code, new[] { "4", "8" }))
		{
			market = MarketBeiJing;
		}

		// 转换市场标识为市场ID
		marketId = market switch
		{
			MarketShangHai => MarketType.MarketIdShangHai,
			MarketShenZhen => MarketType.MarketIdShenZhen,
			MarketBeiJing => MarketType.MarketIdBeiJing,
			MarketHongKong => MarketType.MarketIdHongKong,
			_ => MarketType.MarketIdShangHai
		};
	}

	/// <summary>
	/// 通过市场id和短码判断是否指数
	/// </summary>
	public static bool AssertIndexByMarketAndCode(MarketType marketId, string symbol)
	{
		if (marketId == MarketType.MarketIdShangHai && StartsWithAny(symbol, new[] { "000", "880", "881" }))
		{
			return true;
		}
		if (marketId == MarketType.MarketIdShenZhen && StartsWithAny(symbol, new[] { "399" }))
		{
			return true;
		}
		return false;
	}

	/// <summary>
	/// 通过证券代码判断是否指数
	/// </summary>
	public static bool AssertIndexBySecurityCode(string securityCode)
	{
		DetectMarket(securityCode, out var marketId, out _, out var code);
		return AssertIndexByMarketAndCode(marketId, code);
	}

	/// <summary>
	/// 断言证券代码是否为板块
	/// </summary>
	public static bool AssertBlockBySecurityCode(ref string securityCode)
	{
		DetectMarket(securityCode, out var marketId, out var flag, out var code);

		if (marketId != MarketType.MarketIdShangHai)
		{
			return false;
		}
		if (!StartsWithAny(code, new[] { "880", "881" }))
		{
			return false;
		}

		securityCode = flag + code;
		return true;
	}

	/// <summary>
	/// 通过市场id和代码判断是否ETF
	/// </summary>
	public static bool AssertETFByMarketAndCode(MarketType marketId, string symbol)
	{
		if (marketId == MarketType.MarketIdShangHai && StartsWithAny(symbol, new[] { "51" }))
		{
			return true;
		}
		if (marketId == MarketType.MarketIdShenZhen && StartsWithAny(symbol, new[] { "159" }))
		{
			return true;
		}
		return false;
	}

	/// <summary>
	/// 通过市场id和代码判断是否个股
	/// </summary>
	public static bool AssertStockByMarketAndCode(MarketType marketId, string symbol)
	{
		if (marketId == MarketType.MarketIdShangHai && StartsWithAny(symbol, new[] { "60", "68", "51" }))
		{
			return true;
		}
		if (marketId == MarketType.MarketIdShenZhen && StartsWithAny(symbol, new[] { "00", "30", "159" }))
		{
			return true;
		}
		return false;
	}

	/// <summary>
	/// 通过证券代码判断是否个股
	/// </summary>
	public static bool AssertStockBySecurityCode(string securityCode)
	{
		DetectMarket(securityCode, out var marketId, out _, out var code);
		return AssertStockByMarketAndCode(marketId, code);
	}

	/// <summary>
	/// 修正证券代码
	/// </summary>
	public static string CorrectSecurityCode(string securityCode)
	{
		if (string.IsNullOrEmpty(securityCode))
		{
			return "";
		}
		DetectMarket(securityCode, out _, out var mFlag, out var mSymbol);
		return mFlag + mSymbol;
	}

	/// <summary>
	/// 判断一个代码的类型（股票、指数、板块、ETF）
	/// </summary>
	public static TargetKind AssertCode(string securityCode)
	{
		DetectMarket(securityCode, out var marketId, out _, out var code);

		// 判断是否为板块
		if (marketId == MarketType.MarketIdShangHai && StartsWithAny(code, new[] { "880", "881" }))
		{
			return TargetKind.BLOCK;
		}

		// 判断是否为指数
		if (marketId == MarketType.MarketIdShangHai && StartsWithAny(code, new[] { "000" }))
		{
			return TargetKind.INDEX;
		}
		if (marketId == MarketType.MarketIdShenZhen && StartsWithAny(code, new[] { "399" }))
		{
			return TargetKind.INDEX;
		}

		// 判断是否为ETF
		if (marketId == MarketType.MarketIdShangHai && StartsWithAny(code, new[] { "51" }))
		{
			return TargetKind.ETF;
		}
		if (marketId == MarketType.MarketIdShenZhen && StartsWithAny(code, new[] { "159" }))
		{
			return TargetKind.ETF;
		}

		// 默认为股票
		return TargetKind.STOCK;
	}

	// 辅助方法：判断字符串是否以数组中任意前缀开头
	private static bool StartsWithAny(string str, string[] prefixes)
	{
		if (string.IsNullOrEmpty(str))
		{
			return false;
		}
		return prefixes.Any(prefix => str.StartsWith(prefix));
	}

	// 辅助方法：判断字符串是否以数组中任意后缀结尾
	private static bool EndsWithAny(string str, string[] suffixes)
	{
		if (string.IsNullOrEmpty(str))
		{
			return false;
		}
		return suffixes.Any(suffix => str.EndsWith(suffix));
	}
}
